<template>
  <div ref="stickybox" :style="{ height: height + 'px', zIndex: zIndex }">
    <div
      :class="className"
      :style="{
        top: isSticky ? stickyTop + 'px' : '',
        zIndex: zIndex,
        position: position,
        width: width,
        height: height + 'px'
      }"
    >
      <slot>
        <div>sticky</div>
      </slot>
    </div>
  </div>
</template>

<script>
import {
  reactive,
  toRefs,
  ref,
  onMounted,
  onActivated,
  onUnmounted
} from 'vue';
export default {
  name: 'Sticky',
  props: {
    stickyTop: {
      type: Number,
      default: 0
    },
    zIndex: {
      type: Number,
      default: 1
    },
    className: {
      type: String,
      default: ''
    }
  },
  setup(props) {
    const data = reactive({
      active: false,
      position: '',
      width: undefined,
      height: undefined,
      isSticky: false,
      ...props
    });

    const stickybox = ref(null);

    const sticky = () => {
      if (data.active) {
        return;
      }
      data.position = 'fixed';
      data.active = true;
      data.width = data.width + 'px';
      data.isSticky = true;
    };

    const handleReset = () => {
      if (!data.active) {
        return;
      }
      reset();
    };

    const reset = () => {
      data.position = '';
      data.width = 'auto';
      data.active = false;
      data.isSticky = false;
    };

    const handleScroll = () => {
      const width = stickybox.value.getBoundingClientRect().width;
      data.width = width || 'auto';
      const offsetTop = stickybox.value.getBoundingClientRect().top;
      if (offsetTop < props.stickyTop) {
        sticky();
        return;
      }
      handleReset();
    };

    const handleResize = () => {
      if (data.isSticky) {
        data.width = stickybox.value.getBoundingClientRect().width + 'px';
      }
    };

    onMounted(() => {
      data.height = stickybox.value.getBoundingClientRect().height;
      window.addEventListener('scroll', handleScroll);
      window.addEventListener('resize', handleResize);
    });

    onActivated(() => {
      handleScroll();
    });

    onUnmounted(() => {
      window.removeEventListener('scroll', handleScroll);
      window.removeEventListener('resize', handleResize);
    });
    return {
      ...toRefs(data),
      stickybox
    };
  }
};
</script>
